<?php
class ActivityStreamsPluginFunctions extends SpecialPage{
	function __construct() {
	}
	
	/**
	 * Encode $string so that it can be safely embedded in a XML document
	 *
	 * @param $string String: string to encode
	 * @return String
	 */
	function xmlEncode( $string ) {
		$string = str_replace( "\r\n", "\n", $string );
		$string = preg_replace( '/[\x00-\x08\x0b\x0c\x0e-\x1f]/', '', $string );
		return htmlspecialchars( $string );
	}

	/**
	 * Output the initial XML headers with a stylesheet for legibility
	 * if someone finds it in a browser.
	 * @private
	 */
	function outXmlHeader() {
		global $wgStylePath, $wgStyleVersion;

		$ret = '<?xml version="1.0"?>' . "\n";
		$ret .= '<?xml-stylesheet type="text/css" href="' .
			htmlspecialchars( wfExpandUrl( "$wgStylePath/common/feed.css?$wgStyleVersion" ) ) .
			'"?' . ">\n";
		return $ret;
	}
	
	/**
	 * Return MediaWiki Language Code
	 */
	function getLanguage()
	{
	    global $wgLanguageCode;
	    return $wgLanguageCode;
	}
	
	
	/**
	 * Format a date given a timestamp
	 *
	 * @param $ts Integer: timestamp
	 * @return String: date string
	 */
	function formatTime( $ts ) {
		return gmdate( 'D, d M Y H:i:s \G\M\T', wfTimestamp( TS_UNIX, $ts ) );
	}
	
	/**
	 * Get Feed ID
	 * @return String: feed URI
	 */
	function getFeedURI()
	{
	    return $this->xmlEncode($_SERVER['SCRIPT_URI']);
	}
	
	/**
	 * Get Feed Title
	 * @return String: feed title
	 */
	public function getFeedTitle()
	{
	    global $wgSitename;
	    return $this->xmlEncode($wgSitename.' ActivityStream');
	}

	/**
	 * Ouput an Atom / ActivityStrea.ms header
	 */
	function outHeader() {
		global $wgVersion;
		
		$ret = $this->outXmlHeader().
'<feed xmlns="http://www.w3.org/2005/Atom" xmlns:activity="http://activitystrea.ms/spec/1.0/" xml:lang="'.$this->getLanguage().'">
    <id>'.$this->getFeedURI().'</id>
    <title>'.$this->getFeedTitle().'</title>
    <link rel="self" type="application/atom+xml" href="'.$this->getFeedURI().'"/>
    <updated>'.$this->formatTime( wfTimestampNow() ).'Z</updated>
    <generator>MediaWiki '.$wgVersion.'</generator>';
        return $ret;
    }
	
	/**
	 * Setup and send HTTP headers. Don't send any content;
	 * content might end up being cached and re-sent with
	 * these same headers later.
	 *
	 * This should be called from the outHeader() method,
	 * but can also be called separately.
	 */
	public function httpHeaders() {
		global $wgOut;

		# We take over from $wgOut, excepting its cache header info
		$wgOut->disable();
		$mimetype = $this->contentType();
		header( "Content-type: $mimetype; charset=UTF-8" );
		$wgOut->sendCacheControl();
	}

	/**
	 * Return an internet media type to be sent in the headers.
	 *
	 * @return string
	 * @private
	 */
	function contentType() {
		global $wgRequest;
		$ctype = $wgRequest->getVal('ctype','application/xml');
		$allowedctypes = array('application/xml','text/xml','application/rss+xml','application/atom+xml');
		return (in_array($ctype, $allowedctypes) ? $ctype : 'application/xml');
	}

	/**
	 * Output a given item.
	 * @param $item
	 */
	function outItem( $item )
	{
		global $wgMimeType;
		
		$ret = '
	<entry>
		<id>'.$item['itemURI'].'</id>
		<title>'.$item['title'].'</title>
		<link rel="alternate" type="'.$wgMimeType.'" href="'.$item['itemRcURI'].'"/>';
		
		if( $item['updated'] )
		{
		    $ret .= '
		<updated>'.$this->formatTime( $item['updated'] ).'Z</updated>';
		}
		
		$ret .= '
		<content type="html">'.$item['summary'].'</content>
		<activity:verb>'.$item['verb'].'</activity:verb>
		<activity:object>';
		
		foreach($item['object-type'] as $obj)
		{
		    $ret .= '
		    <activity:object-type>'.$obj.'</activity:object-type>';
		}
		$ret .= '
		    <title>'.$item['title'].'</title>
		    <summary>'.($item['comment'] ? $item['comment'] : $item['summary']).'</summary>
		    <link rel="alternate" type="text/html" href="'.$item['itemURI'].'" />
		</activity:object>
		<author>
		    <name>'.$item['author'].'</name>';
		    
		    if ($item['authorUserId'] != '0')
		    {
		        $ret .= '
		    <uri>'.$item['authorURI'].'</uri>';
		    }
		    
		    $ret .= '
		</author>
	</entry>'."\n";
       return $ret;
    }

	/**
	 * Outputs the footer for Atom 1.0 feed (basicly '\</feed\>').
	 */
	function outFooter()
	{
	    return "\n".'</feed>';
	}
}

?>
